import request from '@/utils/request'

const OSS_ROUTE_PREFIX = '/file/oss'
const MAX_SIZE = 10 * 1024 * 1024 // 10MB

// 统一错误包装
function asError(message, detail) {
  const err = new Error(message)
  if (detail) err.detail = detail
  return err
}

// 上传单个文件到OSS
// options.headers 允许追加自定义请求头（如特殊Token），默认会带全局Authorization
export function uploadFile(file, options = {}) {
  if (!file) return Promise.reject(asError('请选择要上传的文件'))
  if (file.size > MAX_SIZE) return Promise.reject(asError('文件大小不能超过10MB'))

  const formData = new FormData()
  formData.append('file', file)

  return request({
    url: `${OSS_ROUTE_PREFIX}/upload`,
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data',
      ...(options.headers || {})
    },
    timeout: options.timeout || 60_000
  }).catch((e) => {
    throw asError('上传失败，请稍后重试', e)
  })
}

// 批量上传文件到OSS
export function uploadFiles(files, options = {}) {
  if (!Array.isArray(files) || files.length === 0) {
    return Promise.reject(asError('请选择至少一个文件'))
  }
  for (const f of files) {
    if (!f) return Promise.reject(asError('存在无效的文件'))
    if (f.size > MAX_SIZE) return Promise.reject(asError(`文件 ${f.name} 大小超过10MB`))
  }

  const formData = new FormData()
  files.forEach((file) => formData.append('files', file))

  return request({
    url: `${OSS_ROUTE_PREFIX}/uploads`,
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data',
      ...(options.headers || {})
    },
    timeout: options.timeout || 120_000
  }).catch((e) => {
    throw asError('批量上传失败，请稍后重试', e)
  })
}

// 删除OSS文件
export function deleteFile(fileUrl, options = {}) {
  if (!fileUrl) return Promise.reject(asError('文件URL不能为空'))

  return request({
    url: `${OSS_ROUTE_PREFIX}/delete`,
    method: 'delete',
    params: { fileUrl },
    headers: options.headers || {}
  }).catch((e) => {
    throw asError('删除失败，请稍后重试', e)
  })
}

// 检查文件是否存在
export function checkFileExists(fileUrl, options = {}) {
  if (!fileUrl) return Promise.reject(asError('文件URL不能为空'))

  return request({
    url: `${OSS_ROUTE_PREFIX}/exists`,
    method: 'get',
    params: { fileUrl },
    headers: options.headers || {}
  }).catch((e) => {
    throw asError('检查文件存在失败，请稍后重试', e)
  })
}

// 获取文件访问URL
export function getFileUrl(fileName, options = {}) {
  if (!fileName) return Promise.reject(asError('文件名不能为空'))

  return request({
    url: `${OSS_ROUTE_PREFIX}/url`,
    method: 'get',
    params: { fileName },
    headers: options.headers || {}
  }).catch((e) => {
    throw asError('获取文件URL失败，请稍后重试', e)
  })
}

// 获取带签名的文件访问URL（临时访问）
export function getSignedUrl(fileName, expireTime = 3600, options = {}) {
  if (!fileName) return Promise.reject(asError('文件名不能为空'))

  return request({
    url: `${OSS_ROUTE_PREFIX}/signed-url`,
    method: 'get',
    params: { fileName, expireTime },
    headers: options.headers || {}
  }).catch((e) => {
    throw asError('获取签名URL失败，请稍后重试', e)
  })
}

// 带进度的单文件上传（带简单防抖）
export function uploadFileWithProgress(file, onProgress, options = {}) {
  if (!file) return Promise.reject(asError('请选择要上传的文件'))
  if (file.size > MAX_SIZE) return Promise.reject(asError('文件大小不能超过10MB'))

  const formData = new FormData()
  formData.append('file', file)

  let lastEmit = 0
  const emit = (percent) => {
    const now = Date.now()
    if (now - lastEmit > 100 || percent === 100) {
      lastEmit = now
      if (typeof onProgress === 'function') onProgress(percent)
    }
  }

  return request({
    url: `${OSS_ROUTE_PREFIX}/upload`,
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data',
      ...(options.headers || {})
    },
    timeout: options.timeout || 60_000,
    onUploadProgress: (evt) => {
      if (!evt || !evt.total) return
      const percent = Math.round((evt.loaded * 100) / evt.total)
      emit(percent)
    }
  }).catch((e) => {
    throw asError('上传失败，请稍后重试', e)
  })
}

// 工具函数：获取文件大小的可读格式
export function formatFileSize(bytes) {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 工具函数：验证文件扩展名
export function validateFileType(file, allowedTypes = []) {
  if (!file) return false
  if (allowedTypes.length === 0) return true
  const ext = (file.name || '').split('.').pop().toLowerCase()
  return allowedTypes.includes(ext)
}

// 导出常量，便于全局复用和维护
export const OSS_CONFIG = {
  PREFIX: OSS_ROUTE_PREFIX,
  MAX_SIZE
}